/**
 * treeList = [
 *  {
 *      label: 显示名,
 *      _total: 用于后面显示的描述,
 * 
 *      _groupId: 组ID,
 *      children: 孩子节点,
 * 
 *      _itemId: 叶子节点的ID，
 *  }
 * ]
 * 
 */



import * as React from 'react';
import Alert from '../alert'
import {message} from 'antd'
import './index.scss'

// 0：全不选 1：半选 2：全选，用于赋值className
const SELECTTYPE:string[] = [
    "lg-pickerDialog-body-treeNodeIcon-default", // 全部选
    "lg-pickerDialog-body-treeNodeIcon-some", // 半选
    "lg-pickerDialog-body-treeNodeIcon-all", // 全选
] 
// 学校图标类名
const SCHOOLICONCLASSNAME:string[] = [
    "lg-pickerDialog-body-treeRootIcon-high", // 高学
    "lg-pickerDialog-body-treeRootIcon-junior", // 初中
    "lg-pickerDialog-body-treeRootIcon-primary", // 小学
]

export interface PickerDialogProps {
    className: string,
    style: object | string,
    onClose(): any,
    onOk(list: object): void,
    changeSelectType(type): void,
    okText: string,
    closeText: string,
    closeIcon: any,
    visible: boolean,
    treeList: object[],
    selectedList: object[],
    title: any,
    testConsole(value: any): any,
}
 
interface PickerDialogState extends PickerDialogProps {
    showTreeList: object[], // 显示的列表
    currentTree: object, // 当前选中的树节点
    treeClickStep: number[], // 树展开的步骤，怎么走的
    currentSelectType: number, // 按学校：1   按角色：2
    isShowAlert: boolean, // 是否显示提示框
}

export class LgPickerDialog extends React.Component<PickerDialogProps, PickerDialogState> {
    constructor(props: any) {
        super(props);
    }
    // 设置props默认值
    static defaultProps = {
        onClose: () => {},
        onOk: (list: object) => {},
        changeSelectType: (type: number) => {},
        closeIcon: null,
        okText: '确定',
        closeText: '取消',
        treeList: [],
        selectedList: [],
        title: '选择对象',
    }
    componentWillMount(){
        // 初始state
        this.setState({
            selectedList: [],
            treeList: [],
            showTreeList: [],
            treeClickStep: [],
            currentTree: {},
            currentSelectType: 1,
        })
    }
    componentWillReceiveProps(nextProps: any){
        if(nextProps.visible && !this.props.visible){ // 关闭中打开用传进来的selectedList处理treeList树
            this.handleSelectTreeList(nextProps.selectedList, nextProps.treeList)
        }
        if(nextProps.visible && this.props.visible){ // 打开时传值用自身的selectedList处理treeList树
            this.handleSelectTreeList(this.state.selectedList, nextProps.treeList)
        }
    }
    // 恢复默认值
    restoreState(){
        this.setState({
            selectedList: [],
            treeList: [],
            showTreeList: [],
            treeClickStep: [],
            currentTree: {},
            currentSelectType: 1,
        })
    }
    // 处理传进来的树结构
    handleSelectTreeList(selectedList: object[] ,treeList: object[]){
        let selected: object[] = selectedList.slice(0)
        let tree: object[] = treeList.slice(0)
        let {
            groupIds,
            itemIds
        } = this.calcGroupIdsAndItemIds(selected)
        // 设置树的自定义属性
        tree.forEach(item => {
            this.circleSetTreeSelectType(item, groupIds, itemIds)
        })
        this.setState({
            selectedList: selected,
            treeList: tree,
        }, () => {
            this.setCurrentShowTreeList()
        })
    }
    // 传进左边已选择的列表，返回groupIds&itemIds
    calcGroupIdsAndItemIds(selectedList: object[]){
        let selected: object[] = selectedList.slice(0)
        let groupIds: string[] = [], itemIds: string[] = [];
        // 查询已选中的groupId和itemId
        selected.forEach(item => {
            if(item._groupId){
                groupIds.push(item._groupId + '')
            }else if(item._itemId){
                itemIds.push(item._itemId + '')
            }else{
                throw new Error("selectedList中缺少_groupId或者_itemId")
            }
        })
        return {
            groupIds,
            itemIds
        }
    }
    // 从左边已选择的列表中递归树设置__selectType属性，用于显示是否已选择 0：全不选 1：选部分 2：全选
    circleSetTreeSelectType(node: object, groupIds: string[], itemIds: string[], parent: object = {}, notJudge: boolean = false){
        if(!node._groupId && !node._itemId){
            throw new Error("treeList中缺少_groupId或者_itemId")
        }
        if(notJudge){
            node.parent = parent;
            node._selectType = 2
            if(node.children){
                node.children.forEach(item => {
                    this.circleSetTreeSelectType(item, groupIds, itemIds, node, true)
                });
                node._selectNum = node.children.length
            }
            return 2
        }
        node.parent = parent
        let _selectType = 0
        let _selectNum = 0
        let _isSome = false
        if(node.children && node.children.length != 0){ // 有子节点
            if(groupIds.includes(node._groupId)){
                _selectType = 2
                _selectNum = node.children.length
            }
            if(_selectType == 2){ // 如果选择了，子节点不判断，直接赋默认值parent和_selectType = 2
                node.children.forEach(item => {
                    this.circleSetTreeSelectType(item, groupIds, itemIds, node, true)
                });
            }else{
                node.children.forEach(item => {
                    let type: number = this.circleSetTreeSelectType(item, groupIds, itemIds, node)
                    if(type == 2){
                        _selectNum++
                    }
                    if(type == 1){
                        _isSome = true
                    }
                });
                // 子节点全选就设2，有选就设1，否则0
                if(_selectNum == node.children.length){
                    _selectType = 2
                }else if(_selectNum != 0 || _isSome){
                    _selectType = 1
                }else if(_selectNum == 0){
                    _selectType = 0
                } 
            }
        }else if(node._itemId){ // 叶子节点
            if(itemIds.includes(node._itemId)){
                _selectType = 2
            }
        }
        node._selectType = _selectType
        node._selectNum = _selectNum
        return _selectType
    }
    // 获取当前步骤所在的列表
    setCurrentShowTreeList(){
        let tree = this.state.treeList.slice(0)
        let treeClickStep = this.state.treeClickStep.slice(0)
        let len = treeClickStep.length
        let showTreeList = []
        let currentTree = {}
        if(treeClickStep.length == 0){
            showTreeList = tree
        }else{
            currentTree = tree[treeClickStep[0]]
            showTreeList = tree[treeClickStep[0]].children
            for(let i = 1; i < len; i ++){
                currentTree = showTreeList[treeClickStep[i]]
                showTreeList = showTreeList[treeClickStep[i]].children
            } 
        }
        this.setState({
            showTreeList,
            currentTree,
        })
    }
    // 删除某个选中的节点
    deleteNodeItem(index: number){
        let selectedList = this.state.selectedList.slice(0)
        selectedList.splice(index, 1)
        this.handleSelectTreeList(selectedList, this.state.treeList)
    }
    // 返回上几个节点
    preTreeItem(index: number){
        let treeClickStep = this.state.treeClickStep.slice(0)
        for(let i = 0; i < index; i ++){
            treeClickStep.pop()
        }
        this.setState({
            treeClickStep
        }, () => {
            this.setCurrentShowTreeList()
        })
    }
    // 点击树节点进入下一个节点
    nextTreeItem(node: object, index: number){
        if(node._selectType == 2 && this.state.treeClickStep.length != 0){
            return
        }
        let showTreeList = node.children.slice(0)
        let treeClickStep = this.state.treeClickStep.slice(0)
        treeClickStep.push(index)
        this.setState({
            showTreeList,
            currentTree: node,
            treeClickStep,
        })
    }
    // 计算当前层级的面包屑
    calcBreadcrumb(node: object){
        let list = []
        circleGetParent(node, list)
        return list

        // 递归获取父节点，插进list中
        function circleGetParent(node: object, list: object[]){
            if(!node.parent.label){
                return null
            }else{
                list.unshift(node.parent)
                circleGetParent(node.parent, list)
            }
        }
    }
    // 点击选择，计算_selectType并重新渲染,选择树节点
    selectTreeItem(node: object, isAll: boolean = false){
        let selectedList = this.state.selectedList.slice(0)
        let selected = []
        let arr = []
        let type = ''
        switch(node._selectType){
            case 0:
            case 1:
                // 增加
                if(isAll){ // 全选
                    node.children.forEach(item => {
                        let obj = {...item}

                        if(obj._selectType != 2){
                            // 获得半选中选中的id，用于在已选列表中删除
                            this.set_SelectTypeToUnSelect(obj, selected)
                            obj._selectType = 2
                            if(obj.identityName){
                                obj.label= obj.schoolName + obj.identityName
                            }
                            arr.push(obj)
                        }
                    }) 
                }else{
                    let obj = {...node}
                    // 获得半选中选中的id，用于在已选列表中删除
                    this.set_SelectTypeToUnSelect(obj, selected)
                    obj._selectType = 2
                    if(obj.identityName){
                        obj.label= obj.schoolName + obj.identityName
                    }
                    arr.push(obj)
                }
                type = 'add'
                break;
            case 2:
                // 减少
                if(isAll){ // 全选
                    node.children.forEach(item => {
                        if(item._selectType != 0){
                            item._selectType = 0
                            selected.push((item._groupId || item._itemId))
                        }
                    })
                }else{
                    node.selectType = 0
                    selected.push((node._groupId || node._itemId))
                }
                type = 'reduce'
                break;
        }
        // 重新得到selectedList
        if(type === 'add'){
            let list = []
            if(selected.length != 0){
                selectedList.forEach(item => {
                    if(!selected.includes((item._groupId || item._itemId))){
                        list.push(item)
                    }
                });
            }else{
                list = selectedList
            }
            arr = [...list, ...arr]
        }
        if(type === 'reduce' && selected.length != 0){
            selectedList.forEach(item => {
                if(!selected.includes((item._groupId || item._itemId))){
                    arr.push(item)
                }
            });
        }
        this.setState({
            selectedList: arr
        }, () => {
            this.handleSelectTreeList(this.state.selectedList, this.state.treeList)
        })
    }
    // 判断该对象及对象子节点是否存在选择的，如果有选择的也置为未选
    set_SelectTypeToUnSelect(currentTree: object, arr: object[]){
        if(currentTree._selectType == 0){
            return
        }
        console.log('set_SelectTypeToUnSelect', currentTree);
        if(currentTree._groupId){
            if(currentTree._selectType == 2){
                arr.push(item._groupId)
            }else{
                currentTree.children.forEach(item => {
                    this.set_SelectTypeToUnSelect(item, arr)
                }) 
            }
        }else if(currentTree._itemId){
            if(currentTree._selectType == 2){
                arr.push(currentTree._itemId)
            }
        }
    }
    // 关闭弹窗前调用的函数
    beforeClose = () => {
        this.restoreState()
        this.props.onClose()
    }
    // 确定前调用的函数
    beforeOk = () => {
        // 没有选不能确定
        if(this.state.selectedList.length == 0){
            return
        }
        let selectedList = this.state.selectedList.slice(0)
        // 深拷贝,构建新的干净的数据,存在_parent属性会与children属性形成闭环无法使用JSON.stringify函数
        this.cls_parentAttr({children: selectedList})
        this.restoreState()
        this.props.onOk(selectedList)
    }
    // 清除对象children属性下所有的_parent属性
    cls_parentAttr(obj: object){
        obj.children.forEach(item => {
            delete item._parent
            if(item.children && item.children.length != 0){
                this.cls_parentAttr(item)
            }
        })
    }
    // 切换选项 按学校：1 按角色：2
    changeTab(type){
        if(type === this.state.currentSelectType){
            return
        }
        this.setState({
            isShowAlert: true
        })
    }
    // 提示框回调
    alertCallback(data){
        if(data == 'true'){
            this.props.changeSelectType(this.state.currentSelectType == 1? 2: 1)
            this.setState({
                isShowAlert: false,
                currentSelectType: this.state.currentSelectType == 1? 2: 1,
                selectedList: [],
                treeClickStep: [],
            })
        }else{
            this.setState({
                isShowAlert: false
            })
        }
    }
    render() {
        let {
            visible,
            title,
            closeIcon,
            okText,
            closeText,
        } = this.props 
        let {
            selectedList,
            showTreeList,
            currentTree,
            treeClickStep,
            currentSelectType,
        } = this.state
        return ( 
            <div className={`lg-pickerDialog-root ${visible? '': 'lg-pickerDialog-closeDialog'}`}>
                <div className={`lg-pickerDialog-mask`}></div>
                <div className={`lg-pickerDialog-content`}>
                    <div className="lg-pickerDialog-header">
                        <div className="lg-pickerDialog-header-title">
                            {title}
                        </div>
                        <div className="lg-pickerDialog-header-close" onClick={this.beforeClose}>
                            {closeIcon}
                        </div>
                    </div>
                    <div className="lg-pickerDialog-body">
                        <div className="lg-pickerDialog-body-left">
                            <div className="lg-pickerDialog-listContainer">
                                {
                                    selectedList.map((item, index) => {
                                        return (
                                            <div className="lg-pickerDialog-listContainer-item">
                                                <span>{item.label}</span>
                                                <div className="lg-pickerDialog-listContainer-itemClose" onClick={() => {this.deleteNodeItem(index)}}></div>
                                            </div>
                                        )
                                    })
                                }
                            </div>
                            <div className="lg-pickerDialog-btnContainer">
                                <div className={`lg-pickerDialog-btn lg-pickerDialog-btn-ok ${selectedList.length == 0? "lg-pickerDialog-btn-ok-diabled": ''}`} onClick={this.beforeOk}>
                                    {okText}
                                    (已选{selectedList.length})
                                </div>
                                <div className="lg-pickerDialog-btn lg-pickerDialog-btn-close" onClick={this.beforeClose}>{closeText}</div>
                            </div>
                        </div>
                        <div className="lg-pickerDialog-body-right">
                            <div className="lg-pickerDialog-body-selectType">
                                <div 
                                className={`lg-pickerDialog-selectType-item ${currentSelectType == 1? 'lg-pickerDialog-selectType-active': ''}`}
                                onClick={() => {this.changeTab(1)}}
                                >
                                    按学校
                                    <div className="lg-pickerDialog-selectType-underline"></div>
                                </div>
                                <div 
                                className={`lg-pickerDialog-selectType-item ${currentSelectType == 2? 'lg-pickerDialog-selectType-active': ''}`}
                                onClick={() => {this.changeTab(2)}}
                                >
                                    按角色
                                    <div className="lg-pickerDialog-selectType-underline"></div>
                                </div>
                            </div>
                            <div className="lg-pickerDialog-body-treeContainer">
                                {
                                    treeClickStep.length === 0?
                                    // 第一层级，不能选
                                    showTreeList.map((item, index) => {
                                        return (
                                            <div className="lg-pickerDialog-body-treeRootItem" onClick={() => {this.nextTreeItem(item, index)}}>
                                                <span className={`lg-pickerDialog-body-treeRootIcon ${currentSelectType == 1? SCHOOLICONCLASSNAME[index]: 'lg-pickerDialog-body-treeRootIcon-admin'}`}></span>
                                                <span className="lg-pickerDialog-body-treeRootText" title={item.label}>{item.label}</span>
                                            </div>
                                        )
                                    }):
                                    // 非第一层及，可选
                                    <>
                                        <div className="lg-pickerDialog-body-treeNodeHeader">
                                            <div className="lg-pickerDialog-body-treeNodeHeader-top">
                                                <div className="lg-pickerDialog-body-treeNodeHeader-backIcon" onClick={() => {this.preTreeItem(1)}}></div>
                                                <div className="lg-pickerDialog-body-treeNodeHeader-title">{currentTree.label}</div>
                                            </div>
                                            <div className="lg-pickerDialog-body-treeNodeHeader-breadcrumb">
                                                {
                                                    this.calcBreadcrumb(currentTree).map((item, index) => {
                                                        let len = this.calcBreadcrumb(currentTree).length
                                                        return (
                                                            <>
                                                                <span className="lg-pickerDialog-body-treeNodeHeader-breadcrumb-text" onClick={() => {this.preTreeItem(len - index)}}>{item.label}</span>
                                                                <span className="lg-pickerDialog-body-treeNodeHeader-breadcrumb-split"></span>
                                                            </>
                                                        )
                                                    })
                                                }
                                                <span className="lg-pickerDialog-body-treeNodeHeader-breadcrumb-currentText">
                                                    {currentTree.label}
                                                </span>
                                            </div>
                                        </div>
                                        <div className="lg-pickerDialog-body-treeNodeItem" onClick={() => {this.selectTreeItem(currentTree, true)}}>
                                            <span className={`lg-pickerDialog-body-treeNodeIcon ${SELECTTYPE[currentTree._selectType]}`}></span>
                                            <span>全选</span>
                                        </div>
                                        {
                                            showTreeList.map((item, index) => {
                                                return (
                                                    <div className="lg-pickerDialog-body-treeNodeItem">
                                                        <span 
                                                        className={`lg-pickerDialog-body-treeNodeIcon ${SELECTTYPE[item._selectType]}`}
                                                        onClick={() => {this.selectTreeItem(item)}}
                                                        ></span>
                                                        <span 
                                                        className="lg-pickerDialog-body-treeNodeText"
                                                        title={`${item.label}${item._total? `(${item._total})`: ''}`}
                                                        onClick={() => {this.selectTreeItem(item)}}
                                                        >
                                                            {item.label}
                                                            {
                                                                item._total?
                                                                <span className="lg-pickerDialog-body-treeNodeText-total">({item._total})</span>:
                                                                null
                                                            }
                                                        </span>
                                                        {
                                                            item._groupId?
                                                            <span className={`lg-pickerDialog-body-treeNextNodeIcon ${item._selectType == 2? 'lg-pickerDialog-body-treeNextNodeIcon-disabled': ''}`} onClick={() => {this.nextTreeItem(item, index)}}></span>:
                                                            null
                                                        }
                                                    </div>
                                                )
                                            })
                                        }
                                    </>
                                }
                            </div>
                        </div>
                    </div>
                </div>
                
                <Alert
                    className="sendAgain-alert"
                    message="是否切换？选择项将会被清空！"
                    isOpen={this.state.isShowAlert}
                    chooseFn={(data) => { this.alertCallback(data) }}>
                </Alert>
            </div>
        );
    }
}
